package com.lemurian.bankdata.bean;

import org.hibernate.Criteria;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.lemurian.bankdata.bean.base.BaseDaoHibernate;
import com.lemurian.bankdata.lite.logger.BankDataLogger;
import com.lemurian.bankdata.lite.struts.PartialList;
import com.lemurian.entity.Client;

@Repository
public class ClientDAO extends BaseDaoHibernate<Client>{
	
	private BankDataLogger log = BankDataLogger.getLogger(ClientDAO.class.getName());

	@Override
	public PartialList<Client> findByCriteria(int start, int count, Order order, Criterion... criterion){
		PartialList<Client> partialList = null;
		try {
			log.info("Get in");
			// total
			Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Client.class);
			
			criteria.createAlias("debitur", "debitur", Criteria.LEFT_JOIN);
			criteria.createAlias("debitur.status", "status", Criteria.LEFT_JOIN);
			criteria.createAlias("accountOfficer", "accountOfficer");
			criteria.createAlias("department", "department");
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
			
			
			criteria.setCacheable(true);
			for (Criterion c : criterion) {
				criteria.add(c);
			}
			criteria.setProjection(Projections.rowCount());
			int total = ((Integer) criteria.list().iterator().next()).intValue();
			// partial data
			criteria = sessionFactory.getCurrentSession().createCriteria(Client.class);
			
			criteria.createAlias("debitur", "debitur", Criteria.LEFT_JOIN);
			criteria.createAlias("debitur.status", "status", Criteria.LEFT_JOIN);
			criteria.createAlias("accountOfficer", "accountOfficer");
			criteria.createAlias("department", "department");
			criteria.createAlias("accountOfficer", "accountOfficer", CriteriaSpecification.LEFT_JOIN);
			criteria.createAlias("department", "department", CriteriaSpecification.LEFT_JOIN);
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
			
			criteria.setCacheable(true);
			for (Criterion c : criterion) {
				criteria.add(c);
			}
			if (order!=null) criteria.addOrder(order);
			criteria.setFirstResult(start);
			criteria.setMaxResults(count);
			
			partialList = new PartialList<Client>(criteria.list(), total);
		} catch(Exception exception){
			exception.printStackTrace();
			//sessionFactory.getCurrentSession().getTransaction().rollback();
		}
		return partialList;
	}

	public Client loadWithDebitur(int id){
		Client client = null;
		try {
			System.out.println("id : " + id);
			Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Client.class);
			criteria.createAlias("debitur", "debitur");
			criteria.add(Restrictions.eq("id", id));
			criteria.setCacheable(true);
			
			client = (Client) criteria.uniqueResult();
			
			if (client != null) {
				//log.sInfo("Client found with certificate [%s]", client.getCertificate().getName());
				log.sInfo("Client found with debitur [%s]", client.getDebitur().getName());
			}
					
			return client;
		} catch(Exception exception){
			//sessionFactory.getCurrentSession().getTransaction().rollback();
		}
		return client;
	}
	
	public PartialList<Client> findClientForPenandatanganan(int start, int count, Order order, Criterion... criterion){
		PartialList<Client> partialList = null;
		try {
			log.info("Get in findClientForPenandatanganan");
			// total
			Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Client.class);
			criteria.createAlias("debitur", "debitur");
			criteria.createAlias("accountOfficer", "accountOfficer");
			criteria.createAlias("department", "department", CriteriaSpecification.LEFT_JOIN);
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
			
			criteria.setCacheable(true);
			for (Criterion c : criterion) {
				criteria.add(c);
			}
			criteria.setProjection(Projections.rowCount());
			int total = ((Integer) criteria.list().iterator().next()).intValue();
			// partial data
			criteria = sessionFactory.getCurrentSession().createCriteria(Client.class);
			criteria.createAlias("debitur", "debitur");
			criteria.createAlias("accountOfficer", "accountOfficer");
			criteria.createAlias("department", "department",CriteriaSpecification.LEFT_JOIN);
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
			
			criteria.setCacheable(true);
			for (Criterion c : criterion) {
				criteria.add(c);
			}
			if (order!=null) criteria.addOrder(order);
			criteria.setFirstResult(start);
			criteria.setMaxResults(count);
			
			partialList = new PartialList<Client>(criteria.list(), total);
		} catch(Exception exception){
			exception.printStackTrace();
			//sessionFactory.getCurrentSession().getTransaction().rollback();
		}
		return partialList;
	}
	
	public PartialList<Client> daftarKlienPengetikan(int start, int count, Order order, Criterion... criterion) {
		PartialList<Client> partialList = null;
		try {
			log.info("Get in");
			// total
			Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Client.class);
			criteria.createAlias("debitur", "debitur", Criteria.LEFT_JOIN);
			criteria.createAlias("officerType", "officerType", Criteria.LEFT_JOIN);
			criteria.createAlias("department", "department", Criteria.LEFT_JOIN);	
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
			
			criteria.setCacheable(true);
			for (Criterion c : criterion) {
				System.out.println("c : " + c);
				criteria.add(c);
			}
			criteria.setProjection(Projections.rowCount());
			int total = ((Integer) criteria.list().iterator().next()).intValue();
			// partial data
			criteria = sessionFactory.getCurrentSession().createCriteria(Client.class);
			
			criteria.createAlias("debitur", "debitur", Criteria.LEFT_JOIN);
			criteria.createAlias("officerType", "officerType", Criteria.LEFT_JOIN);
			criteria.createAlias("department", "department", Criteria.LEFT_JOIN);
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
			
			criteria.setCacheable(true);
			for (Criterion c : criterion) {
				criteria.add(c);
			}
			if (order!=null) criteria.addOrder(order);
			criteria.setFirstResult(start);
			criteria.setMaxResults(count);
			
			partialList = new PartialList<Client>(criteria.list(), total);
		} catch(Exception exception){
			exception.printStackTrace();
			//sessionFactory.getCurrentSession().getTransaction().rollback();
		}
		return partialList;
	}
	
	public PartialList<Client> findAllClientInformation(int start, int count, Order order, Criterion... criterion) {
		PartialList<Client> partialList = null;
		try {
			log.info("Get in");
			// total
			Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Client.class);
			
			criteria.createCriteria("officerType", "officerType", Criteria.LEFT_JOIN);
			criteria.createCriteria("debitur", "debitur", Criteria.LEFT_JOIN);
			criteria.createCriteria("seller", "seller", Criteria.LEFT_JOIN);
			criteria.createCriteria("accountOfficer", "accountOfficer", Criteria.LEFT_JOIN);
			criteria.createCriteria("marketingHead", "marketingHead", Criteria.LEFT_JOIN);
			criteria.createCriteria("bank", "bank", Criteria.LEFT_JOIN);
			criteria.createCriteria("department", "department", Criteria.LEFT_JOIN);
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
			
			criteria.setCacheable(true);
			for (Criterion c : criterion) {
				criteria.add(c);
			}
			criteria.setProjection(Projections.rowCount());
			int total = ((Integer) criteria.list().iterator().next()).intValue();
			// partial data
			criteria = sessionFactory.getCurrentSession().createCriteria(Client.class);
			
			criteria.createCriteria("officerType", "officerType", Criteria.LEFT_JOIN);
			criteria.createCriteria("debitur", "debitur", Criteria.LEFT_JOIN);
			criteria.createCriteria("seller", "seller", Criteria.LEFT_JOIN);
			criteria.createCriteria("accountOfficer", "accountOfficer", Criteria.LEFT_JOIN);
			criteria.createCriteria("marketingHead", "marketingHead", Criteria.LEFT_JOIN);
			criteria.createCriteria("bank", "bank", Criteria.LEFT_JOIN);
			criteria.createCriteria("department", "department", Criteria.LEFT_JOIN);
			criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
			
			criteria.setCacheable(true);
			for (Criterion c : criterion) {
				criteria.add(c);
			}
			if (order!=null) criteria.addOrder(order);
			criteria.setFirstResult(start);
			criteria.setMaxResults(count);
			
			partialList = new PartialList<Client>(criteria.list(), total);
		} catch(Exception exception){
			exception.printStackTrace();
			//sessionFactory.getCurrentSession().getTransaction().rollback();
		}
		return partialList;
	}
	
	@Override
	public Client load(int id){
		Client client = null;
		try {
			Criteria criteria = getSession().createCriteria(Client.class);
			
			criteria.add(Restrictions.eq("id", id));
			criteria.createCriteria("officerType", "officerType", Criteria.LEFT_JOIN);
			criteria.createCriteria("debitur", "debitur", Criteria.LEFT_JOIN);
			criteria.createCriteria("seller", "seller", Criteria.LEFT_JOIN);
			criteria.createCriteria("accountOfficer", "accountOfficer", Criteria.LEFT_JOIN);
			criteria.createCriteria("marketingHead", "marketingHead", Criteria.LEFT_JOIN);
			criteria.createCriteria("bank", "bank", Criteria.LEFT_JOIN);
			criteria.createCriteria("department", "department", Criteria.LEFT_JOIN);
			
			client = (Client) criteria.uniqueResult();
		} catch(Throwable t){
			t.printStackTrace();
		}
		return client;
	}


	public Client loadClientOnly(int id) {
		Client client = null;
		try {
			Criteria criteria = getSession().createCriteria(Client.class);
			criteria.add(Restrictions.eq("id", id));
			client = (Client) criteria.uniqueResult();
		} catch(Throwable t){
			t.printStackTrace();
		}
		return client;
	}
	
}